#include "temp_capacity_curve.h"

static battery_capacity_table_t* table_s;
static uint8                     table_size_s;

static int8 get_table_size(int8 temp) {
  /* 遍历不同温度下电池容量表，并根据温度返回区间高数组下标 */
  for (uint8 index = 0; index < table_size_s; index++) {
    if (temp <= table_s[index].temp) {
      return index;
    }
  }
  return table_size_s;  // 表格的最大值
}

static float calculate_slope(float x1, float y1, float x2, float y2) {
  if (x2 - x1 != 0) {  // 避免除以零的情况
    float slope = (y2 - y1) / (x2 - x1);
    return slope;
  } else {
    return 0;  // 当x2 = x1时，斜率不存在，默认返回0
  }
}

static float slope_cal(int8 interval_temp_max_index) {
  /* 斜率计算,K = (y1 - y2) / (x1 - x2) */
  /* y = kx */
  int8  interval_temp_min_index = 0;
  float slope_r                 = 0.0;

  if (interval_temp_max_index > 0) {
    interval_temp_min_index = interval_temp_max_index - 1;                                                // 获取区间的最小值的数组下标
    slope_r                 = calculate_slope(table_s[interval_temp_max_index].temp,                      // x1
                                              table_s[interval_temp_max_index].battery_capacity_percent,  // y1
                                              table_s[interval_temp_min_index].temp,                      // x2
                                              table_s[interval_temp_min_index].battery_capacity_percent   // y2
                    );
    // TLOGI(TAG, "slope_r:%f\n", slope_r);
  } else if (interval_temp_max_index == 0) {
    // 表格边界处理
    slope_r = -1;  // 此时最低温度超过最小值，那么再低的温度，此时容量也是70%
  }
  return slope_r;
}

void temp_capacity_curve_init(battery_capacity_table_t* table, uint8 table_size) {
  table_s      = table;
  table_size_s = table_size;
}

uint8 temp_capacity_curve_cur_qmax_percent_cal(int8 temp_now) {
  /* 该接口是计算当前温度在曲线中，容量百分比的 */
  /* 注意，该函数这么写会把小数点后面部分省略 */
  float slope_cal_r;
  float temp                    = 0; /* 临时变量 */
  uint8 cur_qmax                = 0;
  int8  interval_temp_max_index = get_table_size(temp_now);

  if (interval_temp_max_index == table_size_s) {
    // 温度比表格中的最大值还要大
    cur_qmax = table_s[table_size_s - 1].battery_capacity_percent;
  } else {
    // 容量计算
    slope_cal_r = slope_cal(interval_temp_max_index);
    if (slope_cal_r > 0) {
      // y = kx , x = y/k ,x表示容量，y表示温度
      // interval_temp_max_index -1 是为了取区间最小值，获取table_size的函数取的是区间最大值的下标

      temp = MATH_ABS_VAL(table_s[interval_temp_max_index - 1].temp - temp_now) * slope_cal_r;  // 计算出对应温度需要增加的容量(从区间最小值加)

      cur_qmax = table_s[interval_temp_max_index - 1].battery_capacity_percent + temp;
    } else if (slope_cal_r == -1) {
      // 温度比表格中的最小值还要小
      cur_qmax = table_s[0].battery_capacity_percent;
    } else if (slope_cal_r == 0) {
      // 斜率为0 ，只会存在Y1-Y2为0，不会存在X1-X2为0，所以两个点的温度是一样的，返回任意一个即可。
      cur_qmax = table_s[interval_temp_max_index].battery_capacity_percent;
    }
  }

  return cur_qmax;
}

uint16 temp_capacity_curve_real_cur_qmax_cal(int8 temp_now, uint16 cur_qmax) {
  uint8 cur_qmax_percent = temp_capacity_curve_cur_qmax_percent_cal(temp_now);
  return (cur_qmax * cur_qmax_percent) / 100;
}